﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RainEngine.SceneManagement;
using RainEngine.Effects;
using Microsoft.Xna.Framework.Content;
using RainEngine.Rendering;

namespace RainEngine.SceneNodes
{
    /// <summary>
    /// 使用GenericEffect的节点都是从这个类继承的，包括平面、立方体、球体等。    
    /// </summary>
    public abstract class GenericSceneNode :Renderable3DSceneNode,ISceneNodeFog,ISceneNodeLighting  
    {
        /// <summary>
        /// 包含顶点信息的Mesh数据。
        /// </summary>
        protected Mesh mesh;   

        // GenericSceneNode使用的Effect
        protected GenericEffect effectWrapper;

        /// <summary>
        /// 获取GenericSceneNode使用的Effect封装类
        /// </summary>
        public GenericEffect EffectWrapper
        {
            get { return effectWrapper; }
        }        

        /// <summary>
        /// 创建一个新GenericSceneNode对象
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="setScene">所属场景</param>
        /// <param name="setDiffuseTextureName">包含路径的第一张纹理的名称</param>
        /// <param name="setDetailTextureName">包含路径的第二张纹理的名称</param>
        public GenericSceneNode(GraphicsDevice graphicsDevice, ContentManager setContent, Scene setScene, string setDiffuseTextureName, string setDetailTextureName)
            : base(graphicsDevice,setContent,setScene)
        {
            effectWrapper = new GenericEffect();

            if (!string.IsNullOrEmpty(setDiffuseTextureName))
                effectWrapper.DiffuseTexture = content.Load<Texture2D>(setDiffuseTextureName);            
            if (!string.IsNullOrEmpty(setDetailTextureName))
                effectWrapper.DetailTexture = content.Load<Texture2D>(setDetailTextureName);            
            effectWrapper.FogColor = Scene.FogColor;
            effectWrapper.FogStart = Scene.FogStart;
            effectWrapper.FogEnd = Scene.FogEnd;
            effectWrapper.AmbientLightColor = Scene.AmbientLightColor;
            effectWrapper.Light0 = Scene.lights[0];
            effectWrapper.Light1 = Scene.lights[1];
            effectWrapper.Light2 = Scene.lights[2];
        }

        /// <summary>
        /// 初始化CubeSceneNode对象。注意不要使用Initialize，它只被引擎调用。 
        /// </summary>
        public override void Initialize()
        {
            this.UpdateOrder = SceneManagement.SceneNodeOrdering.SceneNode.GetValue();
            base.Initialize();            
        }

        public override int Draw(GameTime gameTime, Matrix ViewMatrix, Matrix ProjectionMatrix, Vector3 CameraPosition)
        {
            mesh.PrepareRender(graphicsDevice);
            effectWrapper.World = Pose.WorldMatrix;
            effectWrapper.View = ViewMatrix;
            effectWrapper.Projection = ProjectionMatrix;
            effectWrapper.EyePosition = CameraPosition;
            effectWrapper.OnApply();
            effectWrapper.effect .CurrentTechnique .Passes[0].Apply();
            mesh.Draw(graphicsDevice);

            return mesh.PrimitivesCount;

        }

        public override void SetClipPlane(Vector4? Plane)
        {
            effectWrapper.ClipPlane = Plane.Value;
        }

        #region ISceneNodeFog接口实现

        public void SetFogColor(Vector3 fogColor)
        {
            effectWrapper.FogColor = fogColor;
        }

        public void SetFogStart(float fogStart)
        {
            effectWrapper.FogStart = fogStart;
        }

        public void SetFogEnd(float fogEnd)
        {
            effectWrapper.FogEnd = fogEnd;
        }

        #endregion

        #region ISceneNodeLighting接口实现

        public void SetAmbientLightColor(Vector3 color)
        {
            effectWrapper.AmbientLightColor = color;
        }

        public void SetLightEnabled(int lightIndex, bool lightEnabled)
        {
            effectWrapper.effect.Parameters["Lights"].Elements[lightIndex].StructureMembers["enabled"].SetValue(lightEnabled); ;
        }

        public void SetLightType(int lightIndex, float value)
        {
            effectWrapper.effect.Parameters["Lights"].Elements[lightIndex].StructureMembers["lightType"].SetValue(value); ;
        }

        public void SetLightVector3(int lightIndex, string parameterName, Vector3 value)
        {
            effectWrapper.effect.Parameters["Lights"].Elements[lightIndex].StructureMembers[parameterName].SetValue(value); ;
        }

        public void SetLightSpotData(int lightIndex, Vector4 setSpotData)
        {
            effectWrapper.effect.Parameters["Lights"].Elements[lightIndex].StructureMembers["spotData"].SetValue(setSpotData);
        }

        #endregion        
    }
}
